/// <reference path="../../index.d.ts" />
let crypto = require("crypto")
let PromWxApi = require("../util/wechat").PromWxApi
/**
 * 微信签名, 消息路由
 * ctx.wechatAccount
 * ctx.wechat 
 */
module.exports = () => {
	/**
	 * @type {import("egg"). CbMiddle}
	 */
	let authWx = async function (ctx, next) {

		if (ctx.method != "POST" && ctx.method != "GET") {
			ctx.status = 404
			return
		}
		// ctx.query = {"app_id": "wxcc5fe7496a53b97d", "signature": "87f966f47f0cf61387877ac58ed43c43ca97ed76", "echostr": "2379277554193265661", "timestamp": "1536127353", "nonce": "702214980"};//debug
		ctx.logger.info("some request data: %j", ctx.query)
		ctx.validate({
			aid: "numstr",
			signature: "alphanum",
			echostr: {
				required: false,
				type: "string"
			},
			timestamp: "numstr",
			nonce: {
				type: "string"
			},
			msg_signature: {
				type: "string",
				required: false
			}
		}, ctx.query)

		let data = (await ctx.app.cache.application).find(function (o) {
			return o.id == ctx.query.aid
		})
		if (!data) {
			ctx.body = "error"
			return
		}
		let signature = ctx.query.signature
		let timestamp = ctx.query.timestamp// todo 时间戳为最新
		let nonce = ctx.query.nonce
		let echostr = ctx.query.echostr
		if (!(signature && timestamp && nonce)) {
			ctx.body = "error"
			return
		}
		let {token, app_id, app_secret, encoding_aeskey, app_type} = data
		ctx.wechat = {token, app_id, app_secret, encoding_aeskey, app_type, aid: ctx.query.aid}

		//1. 将token、timestamp、nonce三个参数进行字典序排序
		let array1 = new Array(token, timestamp, nonce)
		array1.sort()
		let str = array1.toString().replace(/,/g, "")
		//2. 将三个参数字符串拼接成一个字符串进行sha1加密
		let sha1Code = crypto.createHash("sha1")
		let code = sha1Code.update(str, "utf-8").digest("hex")
		//3. 开发者获得加密后的字符串可与signature对比，标识该请求来源于微信
		if (code === signature && ctx.method == "GET") {
			ctx.body = echostr
			return
		} else if (code === signature && ctx.method === "POST") {
			// await this.messageHandle(ctx, next);
			ctx.wechatAccount = PromWxApi.getInstance({
				token: token,
				appid: app_id,
				encodingAESKey: encoding_aeskey,
				AppSecret: app_secret
			})

			await next()
			return
		} else {
			ctx.body = "error"
		}
	}
	return authWx
}
